package net.javamine.util.entityUtils.main;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.javamine.util.DateUtils;
import net.javamine.util.ExceptionUtils;
import net.javamine.util.entityUtils.dao.EntityUtilDao;
import net.javamine.util.entityUtils.entity.ColumnEntity;
import net.javamine.util.entityUtils.utils.TransformDBDataTypeToJavaDataType;
import net.javamine.util.entityUtils.vo.EntityPropertyVo;

import org.apache.log4j.Logger;

import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;


/**
 * 生成MySQL数据库对应的hibernate实体的工具类
 * @author <a href="mailto: java_lht@163.com">Lht</a>
 * @since 2012-11-23
 * @version 1.0
 */
public class CreateHibernateEntityFromMySQLUtils {
	
	private static Logger log = Logger.getLogger(CreateHibernateEntityFromMySQLUtils.class);
	
	/**
	 * 生成实体类的入口方法
	 * @param tableName	数据库表名
	 * @param sourceFolderName	源文件夹名称，例如：src
	 * @param packagePath	包路径，例如：net.javamine.blog.entity
	 * @param entityName	实体类名称，例如：BlogEntity
	 * @throws Exception
	 * 注：需要在实体类属性上注有@Email验证的字段中必须包含"email"子串
	 */
	public static void createEntityFile(String tableName, String sourceFolderName, String packagePath, String entityName) throws Exception {
		EntityUtilDao entityUtilDao = new EntityUtilDao();
		writeEntityToFile(tableName, sourceFolderName, packagePath, entityName, 
				createEntityTemplateList(entityUtilDao.queryTableInfo(tableName)));
	}
	
	/**
	 * 加载freemarker模板，将值赋予模板中，并将实体类写入指定路径
	 * @param tableName	数据库表名
	 * @param sourceFolderName	源文件夹名称，例如：src
	 * @param packagePath	包路径，例如：net.javamine.blog.entity
	 * @param entityName	实体类名称，例如：BlogEntity
	 * @param entityProVoList
	 */
	public static void writeEntityToFile(String tableName, String sourceFolderName, String packagePath, String entityName, List<EntityPropertyVo> entityProVoList) {
		FileOutputStream fos = null;
		try {
			//获取工作空间路径
			String workSpacePath = System.getProperty("user.dir").replace("\\", "/");
			
			Configuration cfg = new Configuration();
			//定义使用本类调用模板
			cfg.setClassForTemplateLoading(CreateHibernateEntityFromMySQLUtils.class, "/net/javamine/util/entityUtils/main");
			//加载freemarker文件路径
			FileTemplateLoader templateLoader = new FileTemplateLoader(new File(workSpacePath + "/WebRoot/WEB-INF/freemarker/"));
			cfg.setTemplateLoader(templateLoader);
			//获取freemarker文件
			Template template = cfg.getTemplate("EntityFreemarker.ftl");
			
//			cfg.setSharedVariable("upperFC", new UpperCaseTransform()); //自定义宏
			
			//定义实体文件夹路径
			StringBuffer folderPathBuf = new StringBuffer();
			folderPathBuf.append(workSpacePath).append("/");
			folderPathBuf.append(sourceFolderName).append("/");
			folderPathBuf.append(packagePath.replace(".", "/")).append("/");
			String filePath = folderPathBuf.toString();
			System.out.println(filePath);
			File entityPathFolder = new File(filePath);
			boolean isMkFile = false; //是否成功创建文件夹或文件
			if (!entityPathFolder.exists()) {
				isMkFile = entityPathFolder.mkdirs();
			}
			
			//定义实体类文件路径及新建文件
			StringBuffer filePathBuf = new StringBuffer();
			filePathBuf.append(filePath).append(entityName).append(".java");
			File entityFile = new File(filePathBuf.toString());
			isMkFile = entityFile.createNewFile();
			
			//加载freemarker中需要的参数，并将参数与模板一并写入到文件中
			if (isMkFile) {
				fos = new FileOutputStream(entityFile);
				
				Map<String, Object> valMap = new HashMap<String, Object>();
				valMap.put("packagePath", packagePath);
				valMap.put("tableName", tableName);
				valMap.put("entityName", entityName);
				valMap.put("date", DateUtils.getDate());
				valMap.put("entityProList", entityProVoList);
				
				template.process(valMap, new OutputStreamWriter(fos, "UTF-8"));
				fos.flush();
				System.out.println("创建完成！");
			} else {
				System.out.println("路径错误或文件已存在，创建失败！");
			}
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (Exception e) {
				ExceptionUtils.getExceptionMessage(log, e);
			}
		}
	}
	
	/**
	 * 生成实体模板List（freemarker中需要的值）
	 * @param colEntityList 含有数据库字段实体的List
	 * @return 含有实体值对象的List
	 */
	public static List<EntityPropertyVo> createEntityTemplateList(List<ColumnEntity> colEntityList) throws Exception {
		List<EntityPropertyVo> entityProVoList = new ArrayList<EntityPropertyVo>();
		for (ColumnEntity colEntity : colEntityList) {
			//根据数据库数据类型type：varchar(20),double(5,2)获取java数据类型及数据的长度或精度
			Map<String, String> map = TransformDBDataTypeToJavaDataType.transformMySQLTypeToJavaTypeAndTypeSize(colEntity.getType());
			EntityPropertyVo vo = new EntityPropertyVo();
			vo.setKey(colEntity.getKey());
			vo.setName(colEntity.getField());
			vo.setType(map.get("javaType"));
			vo.setStringMaxSize(map.get("stringMaxSize"));
			vo.setIntegerMaxSize(map.get("integerMaxSize"));
			vo.setFractionMaxSize(map.get("fractionMaxSize"));
			vo.setComment(colEntity.getComment());
			vo.setPropertyIsNull(colEntity.getNoll().equals("YES") ? true : false);
			entityProVoList.add(vo);
		}
		return entityProVoList;
	}
	
	public static void main(String[] args) {
		try {
			createEntityFile("tb_blog_blogs", "main", "net.javamine.blog.entity", "BlogEntity");
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}
	
}
